package 
{
	
	/**
	 * ...
	 * @author gerry
	 */
	public class SoundManager implements ISoundManager
	{
		import flash.media.Sound;
		import flash.media.SoundChannel;
		import flash.net.URLRequest;
		import flash.events.Event;
		import flash.events.IOErrorEvent;
		import flash.events.ProgressEvent;
		
		import util.SoundUtil;
		
		private	static var	_instance:SoundManager = null;
		
		private var _soundObj:Object = new Object();
		private var _soundChannel:SoundChannel = null;
		//-------------------------------------------------------------------------
		//
		//constructor
		//
		//-------------------------------------------------------------------------
		public function	SoundManager(enforcer:Enforcer):void
		{
			if (_instance != null)
			{
				throw new Error("Only One SoundManager Instance Permited");				
			}
		}
		
		//-------------------------------------------------------------------------
		//
		//static methods
		//
		//-------------------------------------------------------------------------
		public static function getInstance():SoundManager
		{
			if (_instance == null)
			{
				_instance = new SoundManager(new Enforcer());
			}
			
			return _instance;
		}
		
		//-------------------------------------------------------------------------
		//
		//public methods
		//
		//-------------------------------------------------------------------------
		public function play(url:String):void
		{
			if (SoundUtil.urlValid(url, ['mp3']))
			{
				//do something...
				var cleaned:Boolean = cleanSoundObject(_soundObj);
				
				if (cleaned)
				{
					trace('initSoundObjec');
					initSoundObjec(_soundObj, url);					
				}
			}
			else
			{
				//...
			}
		}
		
		public function stop(url:String = null):void
		{
			if (cleanSoundObject(_soundObj))
			{
				_soundChannel.stop();				
			}
		}
		
		//-------------------------------------------------------------------------
		//
		//private methods
		//
		//-------------------------------------------------------------------------
		private function cleanSoundObject(obj:Object):Boolean
		{			
			if (obj != null && obj.hasOwnProperty("sound"))
			{				
				SoundUtil.removeListener(_soundChannel, Event.SOUND_COMPLETE);
				return (delete obj.sound);
			}
			else
			{
				return true;
			}			
		}
		
		private function initSoundObjec(obj:Object, url:String):void
		{
			if (obj != null)
			{
				obj.sound = new Sound(new URLRequest(url));
				addListeners(obj.sound);
				SoundUtil.soundLoaded = false;
				
				_soundChannel = obj.sound.play();
				SoundUtil.addListener(_soundChannel, Event.SOUND_COMPLETE, onSoundComplete);
			}
		}
		
		private function addListeners(sound:Sound):void
		{
			SoundUtil.addListener(sound, Event.OPEN, onSoundOpen);
			SoundUtil.addListener(sound, Event.ID3, onSoundID3);
			SoundUtil.addListener(sound, IOErrorEvent.IO_ERROR, onSoundError);
			SoundUtil.addListener(sound, ProgressEvent.PROGRESS, onSoundProgress);
			SoundUtil.addListener(sound, Event.COMPLETE, onSoundLoaded);
		}
		
		private function removeListeners(sound:Sound):void
		{
			SoundUtil.removeListener(sound, Event.OPEN);
			SoundUtil.removeListener(sound, Event.ID3);
			SoundUtil.removeListener(sound, IOErrorEvent.IO_ERROR);
			SoundUtil.removeListener(sound, ProgressEvent.PROGRESS);
			SoundUtil.removeListener(sound, Event.COMPLETE);
		}
		
		//-------------------------------------------------------------------------
		//
		//event listeners
		//
		//-------------------------------------------------------------------------	
		private function onSoundOpen(e:Event):void
		{
			SoundUtil.info = "加载操作开始";
		}
		
		private function onSoundID3(e:Event):void
		{
			SoundUtil.info = "ID3";
		}
		
		private function onSoundError(e:IOErrorEvent):void
		{
			SoundUtil.info = "出现输入/输出错误并由此导致加载操作失败";
		}
		
		private function onSoundProgress(e:ProgressEvent):void
		{
			SoundUtil.info = (e.bytesLoaded / e.bytesTotal).toFixed(2);
		}
		
		private function onSoundLoaded(e:Event):void
		{
			SoundUtil.info = "成功加载数据";
			SoundUtil.soundLoaded = true;
			SoundUtil.prototype.xinfo = 'ujieiri';
		}
		
		private function onSoundComplete(e:Event):void
		{
			SoundUtil.info = "声音完成播放";
		}
		
		//-------------------------------------------------------------------------
		//
		//getters and setters
		//
		//-------------------------------------------------------------------------
		public function  get playbackProgress():String
		{			
			return SoundUtil.formatTime(_soundChannel.position);			
		}
	}
	
}
class Enforcer{}